#include "result.h"
#include "query_schema.h"
#include "/usr/include/mysql/mysql.h"
#include "assert.h"
#include "string"
#include <list>
using namespace std;

#define SCHEMA_TABLES_COUNT 	512
#define HASH_MASK 				SCHEMA_TABLES_COUNT

struct keyword_result_t
{
	char table_name[16];
	char url_md5[34];
	char url[255];
	int count;
};
keyword_result_t* create_keyword_result(char* table,char* url_md5, char* url, int count)
{
	assert(table != NULL && url != NULL);
	keyword_result_t* k = new keyword_result_t;
	memset(k->table_name,0, sizeof(k->table_name));
	memcpy(k->table_name, table, strlen(table));
	
	memset(k->url_md5,0, sizeof(k->url_md5));
	memcpy(k->url_md5, url_md5, strlen(url_md5));

	memset(k->url,0, sizeof(k->url));
	memcpy(k->url, url, strlen(url));
		
	k->count = count;
	return k;
}
void release_keyword_result(keyword_result_t* keyword_result)
{
	assert(keyword_result != NULL);
	delete keyword_result;
}

static int get_hash(const char* str, int len)
{ 
    unsigned int hash = 2166136261UL;
    for(int i=0;i<len;i++)
        hash = (hash ^ *(str+i)) * 16777619;
    hash += hash << 13;
    hash ^= hash >> 7;
    hash += hash << 3;
    hash ^= hash >> 17;
    hash += hash << 5;
    return hash % HASH_MASK;
}

int find_table_name(const char* p, int len, 
                 const char* pre_table_name, char* table_name)
{
	assert( p != 0 && pre_table_name != 0 && 
		 	table_name != 0 && len > 0);
		 	
	char name[] = "%s_%03d";
	sprintf(table_name, name,pre_table_name, get_hash(p, len));
	return 0;	 	
}

result_union_t* query_from_keyword(MYSQL& mysql,const string& word)
{
	result_union_t* result_union = 0;
	char keyword_table_name[64] = {0};
	const char* szkeyword = word.c_str();
	
	if(find_table_name(szkeyword, word.length(), "KEYWORD", keyword_table_name) !=0)
	{
		return 0;
	}
	
	//NEXT int(8) unsigned NOT NULL default '1',
  	//		COUNT_0 int(8) unsigned ,
  	//		URL_TB_0 varchar(24),
  	//		URL_MD5_0 varchar(33),
  	//		URL_0 varchar(255) NOT NULL, 
  	// 		CHECKDATE_0 date,
  	//		
  //	SELECT K.NEXT, 
   //    K.COUNT_0, K.URL_0,UNIX_TIMESTAMP(K.CHECKDATE_0),
   //    K.COUNT_1, K.URL_1,UNIX_TIMESTAMP(K.CHECKDATE_1),
   //    K.COUNT_2, K.URL_2,UNIX_TIMESTAMP(K.CHECKDATE_2),
   //    K.COUNT_3, K.URL_3,UNIX_TIMESTAMP(K.CHECKDATE_3),
    //   K.COUNT_4, K.URL_4,UNIX_TIMESTAMP(K.CHECKDATE_4),
   //    K.COUNT_5, K.URL_5,UNIX_TIMESTAMP(K.CHECKDATE_5),
  //     K.COUNT_6, K.URL_6,UNIX_TIMESTAMP(K.CHECKDATE_6),
  //     K.COUNT_7, K.URL_7,UNIX_TIMESTAMP(K.CHECKDATE_7), 
  //     K.COUNT_8, K.URL_8,UNIX_TIMESTAMP(K.CHECKDATE_8), 
  //     K.COUNT_9, K.URL_9,UNIX_TIMESTAMP(K.CHECKDATE_9)  
  //FROM keyword_schema.KEYWORD_000 K LIMIT 0,1000
	const char* query = "select t.NEXT, \
		t.COUNT_0,t.URL_0, UNIX_TIMESTAMP(t.CHECKDATE_0),\
		t.COUNT_1,t.URL_1, UNIX_TIMESTAMP(t.CHECKDATE_1),\
		t.COUNT_2,t.URL_2, UNIX_TIMESTAMP(t.CHECKDATE_2),\
		t.COUNT_3,t.URL_3, UNIX_TIMESTAMP(t.CHECKDATE_3),\
		t.COUNT_4,t.URL_4, UNIX_TIMESTAMP(t.CHECKDATE_4),\
		t.COUNT_5,t.URL_5, UNIX_TIMESTAMP(t.CHECKDATE_5),\
		t.COUNT_6,t.URL_6, UNIX_TIMESTAMP(t.CHECKDATE_6),\
		t.COUNT_7,t.URL_7, UNIX_TIMESTAMP(t.CHECKDATE_7),\
		t.COUNT_8,t.URL_8, UNIX_TIMESTAMP(t.CHECKDATE_8),\
		t.COUNT_9,t.URL_9, UNIX_TIMESTAMP(t.CHECKDATE_9) \
			from %s t where t.KEYWORD='%s' order by \
			t.WEIGHT  DESC limit 1	";
	char sql[1024] ={0};
	sprintf(sql, query, keyword_table_name, szkeyword);
	if( mysql_real_query(&mysql, sql, strlen(sql)) )
	{
		printf("query sql %d:%s\n",mysql_errno(&mysql),mysql_error(&mysql));
		return 0;
	}
	MYSQL_RES* res;
	if(( res = mysql_store_result(&mysql)) == NULL)
	{
		printf("store_result sql %d:%s\n",mysql_errno(&mysql),mysql_error(&mysql));
		return 0;
	}
	MYSQL_ROW row = mysql_fetch_row(res);
	if(row == 0)
	{
		mysql_free_result(res);
		return 0;
	}
	int next = atoi(row[0]);
	if(next <= 0)
	{
		mysql_free_result(res);
		return 0;
	}
	result_union = create_result_union(word);
	for(int i = 0; i < next; i++)
	{
		int count = atoi(row[1+i*3]);
		char* url = row[1+i*3+1];
		time_t check_time = (time_t)row[1+i*3+2];
		result_t* result = create_result(url, "", count, check_time);
		add_result(result_union,result);
	}
	mysql_free_result(res);
	return result_union;
}
/* get more detailed information, in future 
result_union_t* query_from_url(MYSQL& mysql,const string& word, list<keyword_result_t*>& results)
{
	char sql[1024] ={0};
	MYSQL_RES* res = 0;
	result_union_t* result_union = create_result_union(word);
	keyword_result_t* item = 0;
	const char* url_query = "select URL, UNIX_TIMESTAMP(CHECKDATE) from %s where MD5='%s'";
	list<keyword_result_t*>::iterator it =  results.begin();
	for(; it != results.end(); it++)
	{
		item = (*it);
		memset(sql, 0,sizeof(sql));
		sprintf(sql, url_query, item->table_name,item->url_md5);
		if( mysql_real_query(&mysql, sql, strlen(sql)) )
		{
			printf("query sql %d:%s\n",mysql_errno(&mysql),mysql_error(&mysql));
			continue;
		}
		
		if(( res = mysql_store_result(&mysql)) == NULL)
		{
			printf("store_result sql %d:%s\n",mysql_errno(&mysql),mysql_error(&mysql));
			continue;
		}
		MYSQL_ROW row = mysql_fetch_row(res);
		if(row == 0)
		{
			continue;
		}
		char* url = row[0];
		time_t check_time = (time_t)row[1];
		result_t* result = create_result(url, "", item->count, check_time);
		add_result(result_union,result);
		
		release_keyword_result(item);
		mysql_free_result(res);
	}
	results.clear();
	return result_union;
}
*/

result_union_t* query_schema(const string& word)
{
	MYSQL mysql;
	mysql_init(&mysql);
	if(!mysql_real_connect(&mysql, "localhost",
		"webroot", "123456","keyword_schema", 0, NULL, 0))
	{
		printf("error, connect \n");
		return 0;
	}
	
	result_union_t* result_union = query_from_keyword(mysql, word);
	
	mysql_close(&mysql);
	return result_union;
	
}
